1   /*                        __    __  __  __    __  ___
2    *                       \  \  /  /    \  \  /  /  __/
3    *                        \  \/  /  /\  \  \/  /  /
4    *                         \____/__/  \__\____/__/.ɪᴏ
5    * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
6    */
7   package io.vavr.collection;
8   
9   import io.vavr.*;
10  import io.vavr.control.Option;
11  
12  import java.util.*;
13  import java.util.function.*;
14  import java.util.stream.Collector;
15  
16  import static io.vavr.collection.JavaConverters.ChangePolicy.IMMUTABLE;
17  import static io.vavr.collection.JavaConverters.ChangePolicy.MUTABLE;
18  
19  /**
20   * An immutable {@code Queue} stores elements allowing a first-in-first-out (FIFO) retrieval.
21   * <p>
22   * Queue API:
23   *
24   * <ul>
25   * <li>{@link #dequeue()}</li>
26   * <li>{@link #dequeueOption()}</li>
27   * <li>{@link #enqueue(Object)}</li>
28   * <li>{@link #enqueue(Object[])}</li>
29   * <li>{@link #enqueueAll(Iterable)}</li>
30   * <li>{@link #peek()}</li>
31   * <li>{@link #peekOption()}</li>
32   * </ul>
33   *
34   * A Queue internally consists of a front List containing the front elements of the Queue in the correct order and a
35   * rear List containing the rear elements of the Queue in reverse order.
36   * <p>
37   * When the front list is empty, front and rear are swapped and rear is reversed. This implies the following queue
38   * invariant: {@code front.isEmpty() => rear.isEmpty()}.
39   * <p>
40   * See Okasaki, Chris: <em>Purely Functional Data Structures</em> (p. 42 ff.). Cambridge, 2003.
41   *
42   * @param <T> Component type of the Queue
43   * @author Daniel Dietrich
44   */
45  public final class Queue<T> extends AbstractQueue<T, Queue<T>> implements LinearSeq<T> {
46  
47      private static final long serialVersionUID = 1L;
48  
49      private static final Queue<?> EMPTY = new Queue<>(io.vavr.collection.List.empty(), io.vavr.collection.List.empty());
50  
51      private final io.vavr.collection.List<T> front;
52      private final io.vavr.collection.List<T> rear;
53  
54      /**
55       * Creates a Queue consisting of a front List and a rear List.
56       * <p>
57       * For a {@code Queue(front, rear)} the following invariant holds: {@code Queue is empty <=> front is empty}.
58       * In other words: If the Queue is not empty, the front List contains at least one element.
59       *
60       * @param front A List of front elements, in correct order.
61       * @param rear  A List of rear elements, in reverse order.
62       */
63      private Queue(io.vavr.collection.List<T> front, io.vavr.collection.List<T> rear) {
64          final boolean frontIsEmpty = front.isEmpty();
65          this.front = frontIsEmpty ? rear.reverse() : front;
66          this.rear = frontIsEmpty ? front : rear;
67      }
68  
69      /**
70       * Returns a {@link java.util.stream.Collector} which may be used in conjunction with
71       * {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link Queue}
72       * .
73       *
74       * @param <T> Component type of the Queue.
75       * @return A io.vavr.collection.Queue Collector.
76       */
77      public static <T> Collector<T, ArrayList<T>, Queue<T>> collector() {
78          final Supplier<ArrayList<T>> supplier = ArrayList::new;
79          final BiConsumer<ArrayList<T>, T> accumulator = ArrayList::add;
80          final BinaryOperator<ArrayList<T>> combiner = (left, right) -> {
81              left.addAll(right);
82              return left;
83          };
84          final Function<ArrayList<T>, Queue<T>> finisher = Queue::ofAll;
85          return Collector.of(supplier, accumulator, combiner, finisher);
86      }
87  
88      /**
89       * Returns the empty Queue.
90       *
91       * @param <T> Component type
92       * @return The empty Queue.
93       */
94      @SuppressWarnings("unchecked")
95      public static <T> Queue<T> empty() {
96          return (Queue<T>) EMPTY;
97      }
98  
99      /**
100      * Narrows a widened {@code Queue<? extends T>} to {@code Queue<T>}
101      * by performing a type-safe cast. This is eligible because immutable/read-only
102      * collections are covariant.
103      *
104      * @param queue An {@code Queue}.
105      * @param <T>   Component type of the {@code Queue}.
106      * @return the given {@code queue} instance as narrowed type {@code Queue<T>}.
107      */
108     @SuppressWarnings("unchecked")
109     public static <T> Queue<T> narrow(Queue<? extends T> queue) {
110         return (Queue<T>) queue;
111     }
112 
113     /**
114      * Returns a singleton {@code Queue}, i.e. a {@code Queue} of one element.
115      *
116      * @param element An element.
117      * @param <T>     The component type
118      * @return A new Queue instance containing the given element
119      */
120     public static <T> Queue<T> of(T element) {
121         return ofAll(io.vavr.collection.List.of(element));
122     }
123 
124     /**
125      * Creates a Queue of the given elements.
126      *
127      * @param <T>      Component type of the Queue.
128      * @param elements Zero or more elements.
129      * @return A queue containing the given elements in the same order.
130      * @throws NullPointerException if {@code elements} is null
131      */
132     @SuppressWarnings("varargs")
133     @SafeVarargs
134     public static <T> Queue<T> of(T... elements) {
135         Objects.requireNonNull(elements, "elements is null");
136         return ofAll(io.vavr.collection.List.of(elements));
137     }
138 
139     /**
140      * Creates a Queue of the given elements.
141      *
142      * @param <T>      Component type of the Queue.
143      * @param elements An Iterable of elements.
144      * @return A queue containing the given elements in the same order.
145      * @throws NullPointerException if {@code elements} is null
146      */
147     @SuppressWarnings("unchecked")
148     public static <T> Queue<T> ofAll(Iterable<? extends T> elements) {
149         Objects.requireNonNull(elements, "elements is null");
150         if (elements instanceof Queue) {
151             return (Queue<T>) elements;
152         } else if (!elements.iterator().hasNext()) {
153             return empty();
154         } else if (elements instanceof io.vavr.collection.List) {
155             return new Queue<>((io.vavr.collection.List<T>) elements, io.vavr.collection.List.empty());
156         } else {
157             return new Queue<>(io.vavr.collection.List.ofAll(elements), io.vavr.collection.List.empty());
158         }
159     }
160 
161     /**
162      * Creates a Queue that contains the elements of the given {@link java.util.stream.Stream}.
163      *
164      * @param javaStream A {@link java.util.stream.Stream}
165      * @param <T>        Component type of the Stream.
166      * @return A Queue containing the given elements in the same order.
167      */
168     public static <T> Queue<T> ofAll(java.util.stream.Stream<? extends T> javaStream) {
169         Objects.requireNonNull(javaStream, "javaStream is null");
170         return new Queue<>(io.vavr.collection.List.ofAll(javaStream), io.vavr.collection.List.empty());
171     }
172 
173     /**
174      * Creates a Queue from boolean values.
175      *
176      * @param elements boolean values
177      * @return A new Queue of Boolean values
178      * @throws NullPointerException if elements is null
179      */
180     public static Queue<Boolean> ofAll(boolean... elements) {
181         Objects.requireNonNull(elements, "elements is null");
182         return ofAll(io.vavr.collection.List.ofAll(elements));
183     }
184 
185     /**
186      * Creates a Queue from byte values.
187      *
188      * @param elements byte values
189      * @return A new Queue of Byte values
190      * @throws NullPointerException if elements is null
191      */
192     public static Queue<Byte> ofAll(byte... elements) {
193         Objects.requireNonNull(elements, "elements is null");
194         return ofAll(io.vavr.collection.List.ofAll(elements));
195     }
196 
197     /**
198      * Creates a Queue from char values.
199      *
200      * @param elements char values
201      * @return A new Queue of Character values
202      * @throws NullPointerException if elements is null
203      */
204     public static Queue<Character> ofAll(char... elements) {
205         Objects.requireNonNull(elements, "elements is null");
206         return ofAll(io.vavr.collection.List.ofAll(elements));
207     }
208 
209     /**
210      * Creates a Queue from double values.
211      *
212      * @param elements double values
213      * @return A new Queue of Double values
214      * @throws NullPointerException if elements is null
215      */
216     public static Queue<Double> ofAll(double... elements) {
217         Objects.requireNonNull(elements, "elements is null");
218         return ofAll(io.vavr.collection.List.ofAll(elements));
219     }
220 
221     /**
222      * Creates a Queue from float values.
223      *
224      * @param elements float values
225      * @return A new Queue of Float values
226      * @throws NullPointerException if elements is null
227      */
228     public static Queue<Float> ofAll(float... elements) {
229         Objects.requireNonNull(elements, "elements is null");
230         return ofAll(io.vavr.collection.List.ofAll(elements));
231     }
232 
233     /**
234      * Creates a Queue from int values.
235      *
236      * @param elements int values
237      * @return A new Queue of Integer values
238      * @throws NullPointerException if elements is null
239      */
240     public static Queue<Integer> ofAll(int... elements) {
241         Objects.requireNonNull(elements, "elements is null");
242         return ofAll(io.vavr.collection.List.ofAll(elements));
243     }
244 
245     /**
246      * Creates a Queue from long values.
247      *
248      * @param elements  long values
249      * @return A new Queue of Long values
250      * @throws NullPointerException if elements is null
251      */
252     public static Queue<Long> ofAll(long... elements) {
253         Objects.requireNonNull(elements, "elements is null");
254         return ofAll(io.vavr.collection.List.ofAll(elements));
255     }
256 
257     /**
258      * Creates a Queue from short values.
259      *
260      * @param elements short values
261      * @return A new Queue of Short values
262      * @throws NullPointerException if elements is null
263      */
264     public static Queue<Short> ofAll(short... elements) {
265         Objects.requireNonNull(elements, "elements is null");
266         return ofAll(io.vavr.collection.List.ofAll(elements));
267     }
268 
269     /**
270      * Returns a Queue containing {@code n} values of a given Function {@code f}
271      * over a range of integer values from 0 to {@code n - 1}.
272      *
273      * @param <T> Component type of the Queue
274      * @param n   The number of elements in the Queue
275      * @param f   The Function computing element values
276      * @return A Queue consisting of elements {@code f(0),f(1), ..., f(n - 1)}
277      * @throws NullPointerException if {@code f} is null
278      */
279     public static <T> Queue<T> tabulate(int n, Function<? super Integer, ? extends T> f) {
280         Objects.requireNonNull(f, "f is null");
281         return io.vavr.collection.Collections.tabulate(n, f, empty(), Queue::of);
282     }
283 
284     /**
285      * Returns a Queue containing {@code n} values supplied by a given Supplier {@code s}.
286      *
287      * @param <T> Component type of the Queue
288      * @param n   The number of elements in the Queue
289      * @param s   The Supplier computing element values
290      * @return An Queue of size {@code n}, where each element contains the result supplied by {@code s}.
291      * @throws NullPointerException if {@code s} is null
292      */
293     public static <T> Queue<T> fill(int n, Supplier<? extends T> s) {
294         Objects.requireNonNull(s, "s is null");
295         return io.vavr.collection.Collections.fill(n, s, empty(), Queue::of);
296     }
297 
298     public static Queue<Character> range(char from, char toExclusive) {
299         return ofAll(Iterator.range(from, toExclusive));
300     }
301 
302     public static Queue<Character> rangeBy(char from, char toExclusive, int step) {
303         return ofAll(Iterator.rangeBy(from, toExclusive, step));
304     }
305 
306     @GwtIncompatible
307     public static Queue<Double> rangeBy(double from, double toExclusive, double step) {
308         return ofAll(Iterator.rangeBy(from, toExclusive, step));
309     }
310 
311     /**
312      * Creates a Queue of int numbers starting from {@code from}, extending to {@code toExclusive - 1}.
313      * <p>
314      * Examples:
315      * <pre>
316      * <code>
317      * Queue.range(0, 0)  // = Queue()
318      * Queue.range(2, 0)  // = Queue()
319      * Queue.range(-2, 2) // = Queue(-2, -1, 0, 1)
320      * </code>
321      * </pre>
322      *
323      * @param from        the first number
324      * @param toExclusive the last number + 1
325      * @return a range of int values as specified or {@code Nil} if {@code from >= toExclusive}
326      */
327     public static Queue<Integer> range(int from, int toExclusive) {
328         return ofAll(Iterator.range(from, toExclusive));
329     }
330 
331     /**
332      * Creates a Queue of int numbers starting from {@code from}, extending to {@code toExclusive - 1},
333      * with {@code step}.
334      * <p>
335      * Examples:
336      * <pre>
337      * <code>
338      * Queue.rangeBy(1, 3, 1)  // = Queue(1, 2)
339      * Queue.rangeBy(1, 4, 2)  // = Queue(1, 3)
340      * Queue.rangeBy(4, 1, -2) // = Queue(4, 2)
341      * Queue.rangeBy(4, 1, 2)  // = Queue()
342      * </code>
343      * </pre>
344      *
345      * @param from        the first number
346      * @param toExclusive the last number + 1
347      * @param step        the step
348      * @return a range of long values as specified or {@code Nil} if<br>
349      * {@code from >= toInclusive} and {@code step > 0} or<br>
350      * {@code from <= toInclusive} and {@code step < 0}
351      * @throws IllegalArgumentException if {@code step} is zero
352      */
353     public static Queue<Integer> rangeBy(int from, int toExclusive, int step) {
354         return ofAll(Iterator.rangeBy(from, toExclusive, step));
355     }
356 
357     /**
358      * Creates a Queue of long numbers starting from {@code from}, extending to {@code toExclusive - 1}.
359      * <p>
360      * Examples:
361      * <pre>
362      * <code>
363      * Queue.range(0L, 0L)  // = Queue()
364      * Queue.range(2L, 0L)  // = Queue()
365      * Queue.range(-2L, 2L) // = Queue(-2L, -1L, 0L, 1L)
366      * </code>
367      * </pre>
368      *
369      * @param from        the first number
370      * @param toExclusive the last number + 1
371      * @return a range of long values as specified or {@code Nil} if {@code from >= toExclusive}
372      */
373     public static Queue<Long> range(long from, long toExclusive) {
374         return ofAll(Iterator.range(from, toExclusive));
375     }
376 
377     /**
378      * Creates a Queue of long numbers starting from {@code from}, extending to {@code toExclusive - 1},
379      * with {@code step}.
380      * <p>
381      * Examples:
382      * <pre>
383      * <code>
384      * Queue.rangeBy(1L, 3L, 1L)  // = Queue(1L, 2L)
385      * Queue.rangeBy(1L, 4L, 2L)  // = Queue(1L, 3L)
386      * Queue.rangeBy(4L, 1L, -2L) // = Queue(4L, 2L)
387      * Queue.rangeBy(4L, 1L, 2L)  // = Queue()
388      * </code>
389      * </pre>
390      *
391      * @param from        the first number
392      * @param toExclusive the last number + 1
393      * @param step        the step
394      * @return a range of long values as specified or {@code Nil} if<br>
395      * {@code from >= toInclusive} and {@code step > 0} or<br>
396      * {@code from <= toInclusive} and {@code step < 0}
397      * @throws IllegalArgumentException if {@code step} is zero
398      */
399     public static Queue<Long> rangeBy(long from, long toExclusive, long step) {
400         return ofAll(Iterator.rangeBy(from, toExclusive, step));
401     }
402 
403     public static Queue<Character> rangeClosed(char from, char toInclusive) {
404         return ofAll(Iterator.rangeClosed(from, toInclusive));
405     }
406 
407     public static Queue<Character> rangeClosedBy(char from, char toInclusive, int step) {
408         return ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
409     }
410 
411     @GwtIncompatible
412     public static Queue<Double> rangeClosedBy(double from, double toInclusive, double step) {
413         return ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
414     }
415 
416     /**
417      * Creates a Queue of int numbers starting from {@code from}, extending to {@code toInclusive}.
418      * <p>
419      * Examples:
420      * <pre>
421      * <code>
422      * Queue.rangeClosed(0, 0)  // = Queue(0)
423      * Queue.rangeClosed(2, 0)  // = Queue()
424      * Queue.rangeClosed(-2, 2) // = Queue(-2, -1, 0, 1, 2)
425      * </code>
426      * </pre>
427      *
428      * @param from        the first number
429      * @param toInclusive the last number
430      * @return a range of int values as specified or {@code Nil} if {@code from > toInclusive}
431      */
432     public static Queue<Integer> rangeClosed(int from, int toInclusive) {
433         return ofAll(Iterator.rangeClosed(from, toInclusive));
434     }
435 
436     /**
437      * Creates a Queue of int numbers starting from {@code from}, extending to {@code toInclusive},
438      * with {@code step}.
439      * <p>
440      * Examples:
441      * <pre>
442      * <code>
443      * Queue.rangeClosedBy(1, 3, 1)  // = Queue(1, 2, 3)
444      * Queue.rangeClosedBy(1, 4, 2)  // = Queue(1, 3)
445      * Queue.rangeClosedBy(4, 1, -2) // = Queue(4, 2)
446      * Queue.rangeClosedBy(4, 1, 2)  // = Queue()
447      * </code>
448      * </pre>
449      *
450      * @param from        the first number
451      * @param toInclusive the last number
452      * @param step        the step
453      * @return a range of int values as specified or {@code Nil} if<br>
454      * {@code from > toInclusive} and {@code step > 0} or<br>
455      * {@code from < toInclusive} and {@code step < 0}
456      * @throws IllegalArgumentException if {@code step} is zero
457      */
458     public static Queue<Integer> rangeClosedBy(int from, int toInclusive, int step) {
459         return ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
460     }
461 
462     /**
463      * Creates a Queue of long numbers starting from {@code from}, extending to {@code toInclusive}.
464      * <p>
465      * Examples:
466      * <pre>
467      * <code>
468      * Queue.rangeClosed(0L, 0L)  // = Queue(0L)
469      * Queue.rangeClosed(2L, 0L)  // = Queue()
470      * Queue.rangeClosed(-2L, 2L) // = Queue(-2L, -1L, 0L, 1L, 2L)
471      * </code>
472      * </pre>
473      *
474      * @param from        the first number
475      * @param toInclusive the last number
476      * @return a range of long values as specified or {@code Nil} if {@code from > toInclusive}
477      */
478     public static Queue<Long> rangeClosed(long from, long toInclusive) {
479         return ofAll(Iterator.rangeClosed(from, toInclusive));
480     }
481 
482     /**
483      * Transposes the rows and columns of a {@link Queue} matrix.
484      *
485      * @param <T> matrix element type
486      * @param matrix to be transposed.
487      * @return a transposed {@link Queue} matrix.
488      * @throws IllegalArgumentException if the row lengths of {@code matrix} differ.
489      *
490      * <p>
491      * ex: {@code
492      * Queue.transpose(Queue(Queue(1,2,3), Queue(4,5,6))) → Queue(Queue(1,4), Queue(2,5), Queue(3,6))
493      * }
494      */
495     public static <T> Queue<Queue<T>> transpose(Queue<Queue<T>> matrix) {
496         return io.vavr.collection.Collections.transpose(matrix, Queue::ofAll, Queue::of);
497     }
498 
499     /**
500      * Creates a Queue of long numbers starting from {@code from}, extending to {@code toInclusive},
501      * with {@code step}.
502      * <p>
503      * Examples:
504      * <pre>
505      * <code>
506      * Queue.rangeClosedBy(1L, 3L, 1L)  // = Queue(1L, 2L, 3L)
507      * Queue.rangeClosedBy(1L, 4L, 2L)  // = Queue(1L, 3L)
508      * Queue.rangeClosedBy(4L, 1L, -2L) // = Queue(4L, 2L)
509      * Queue.rangeClosedBy(4L, 1L, 2L)  // = Queue()
510      * </code>
511      * </pre>
512      *
513      * @param from        the first number
514      * @param toInclusive the last number
515      * @param step        the step
516      * @return a range of int values as specified or {@code Nil} if<br>
517      * {@code from > toInclusive} and {@code step > 0} or<br>
518      * {@code from < toInclusive} and {@code step < 0}
519      * @throws IllegalArgumentException if {@code step} is zero
520      */
521     public static Queue<Long> rangeClosedBy(long from, long toInclusive, long step) {
522         return ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
523     }
524 
525     /**
526      * Creates a Queue from a seed value and a function.
527      * The function takes the seed at first.
528      * The function should return {@code None} when it's
529      * done generating the Queue, otherwise {@code Some} {@code Tuple}
530      * of the element for the next call and the value to add to the
531      * resulting Queue.
532      * <p>
533      * Example:
534      * <pre>
535      * <code>
536      * Queue.unfoldRight(10, x -&gt; x == 0
537      *             ? Option.none()
538      *             : Option.of(new Tuple2&lt;&gt;(x, x-1)));
539      * // Queue(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
540      * </code>
541      * </pre>
542      *
543      * @param <T>  type of seeds
544      * @param <U>  type of unfolded values
545      * @param seed the start value for the iteration
546      * @param f    the function to get the next step of the iteration
547      * @return a Queue with the values built up by the iteration
548      * @throws NullPointerException if {@code f} is null
549      */
550     public static <T, U> Queue<U> unfoldRight(T seed, Function<? super T, Option<Tuple2<? extends U, ? extends T>>> f) {
551         return Iterator.unfoldRight(seed, f).toQueue();
552     }
553 
554     /**
555      * Creates a Queue from a seed value and a function.
556      * The function takes the seed at first.
557      * The function should return {@code None} when it's
558      * done generating the Queue, otherwise {@code Some} {@code Tuple}
559      * of the value to add to the resulting Queue and
560      * the element for the next call.
561      * <p>
562      * Example:
563      * <pre>
564      * <code>
565      * Queue.unfoldLeft(10, x -&gt; x == 0
566      *             ? Option.none()
567      *             : Option.of(new Tuple2&lt;&gt;(x-1, x)));
568      * // Queue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
569      * </code>
570      * </pre>
571      *
572      * @param <T>  type of seeds
573      * @param <U>  type of unfolded values
574      * @param seed the start value for the iteration
575      * @param f    the function to get the next step of the iteration
576      * @return a Queue with the values built up by the iteration
577      * @throws NullPointerException if {@code f} is null
578      */
579     public static <T, U> Queue<U> unfoldLeft(T seed, Function<? super T, Option<Tuple2<? extends T, ? extends U>>> f) {
580         return Iterator.unfoldLeft(seed, f).toQueue();
581     }
582 
583     /**
584      * Creates a Queue from a seed value and a function.
585      * The function takes the seed at first.
586      * The function should return {@code None} when it's
587      * done generating the Queue, otherwise {@code Some} {@code Tuple}
588      * of the value to add to the resulting Queue and
589      * the element for the next call.
590      * <p>
591      * Example:
592      * <pre>
593      * <code>
594      * Queue.unfold(10, x -&gt; x == 0
595      *             ? Option.none()
596      *             : Option.of(new Tuple2&lt;&gt;(x-1, x)));
597      * // Queue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
598      * </code>
599      * </pre>
600      *
601      * @param <T>  type of seeds and unfolded values
602      * @param seed the start value for the iteration
603      * @param f    the function to get the next step of the iteration
604      * @return a Queue with the values built up by the iteration
605      * @throws NullPointerException if {@code f} is null
606      */
607     public static <T> Queue<T> unfold(T seed, Function<? super T, Option<Tuple2<? extends T, ? extends T>>> f) {
608         return Iterator.unfold(seed, f).toQueue();
609     }
610 
611     /**
612      * Enqueues a new element.
613      *
614      * @param element The new element
615      * @return a new {@code Queue} instance, containing the new element
616      */
617     @Override
618     public Queue<T> enqueue(T element) {
619         return new Queue<>(front, rear.prepend(element));
620     }
621 
622     /**
623      * Enqueues the given elements. A queue has FIFO order, i.e. the first of the given elements is
624      * the first which will be retrieved.
625      *
626      * @param elements An Iterable of elements, may be empty
627      * @return a new {@code Queue} instance, containing the new elements
628      * @throws NullPointerException if elements is null
629      */
630     @SuppressWarnings("unchecked")
631     public Queue<T> enqueueAll(Iterable<? extends T> elements) {
632         Objects.requireNonNull(elements, "elements is null");
633         if (isEmpty() && elements instanceof Queue) {
634             return (Queue<T>) elements;
635         } else {
636             return io.vavr.collection.List.ofAll(elements).foldLeft(this, Queue::enqueue);
637         }
638     }
639 
640     // -- Adjusted return types of Seq methods
641 
642     @Override
643     public Queue<T> append(T element) {
644         return enqueue(element);
645     }
646 
647     @Override
648     public Queue<T> appendAll(Iterable<? extends T> elements) {
649         return enqueueAll(elements);
650     }
651 
652     @Override
653     public java.util.List<T> asJava() {
654         return JavaConverters.asJava(this, IMMUTABLE);
655     }
656 
657     @Override
658     public Queue<T> asJava(Consumer<? super java.util.List<T>> action) {
659         return Collections.asJava(this, action, IMMUTABLE);
660     }
661 
662     @Override
663     public java.util.List<T> asJavaMutable() {
664         return JavaConverters.asJava(this, MUTABLE);
665     }
666 
667     @Override
668     public Queue<T> asJavaMutable(Consumer<? super java.util.List<T>> action) {
669         return Collections.asJava(this, action, MUTABLE);
670     }
671 
672     @Override
673     public <R> Queue<R> collect(PartialFunction<? super T, ? extends R> partialFunction) {
674         return ofAll(iterator().<R> collect(partialFunction));
675     }
676     
677     @Override
678     public Queue<Queue<T>> combinations() {
679         return ofAll(toList().combinations().map(Queue::ofAll));
680     }
681 
682     @Override
683     public Queue<Queue<T>> combinations(int k) {
684         return ofAll(toList().combinations(k).map(Queue::ofAll));
685     }
686 
687     @Override
688     public Iterator<Queue<T>> crossProduct(int power) {
689         return io.vavr.collection.Collections.crossProduct(empty(), this, power);
690     }
691 
692     @Override
693     public Queue<T> distinct() {
694         return ofAll(toList().distinct());
695     }
696 
697     @Override
698     public Queue<T> distinctBy(Comparator<? super T> comparator) {
699         Objects.requireNonNull(comparator, "comparator is null");
700         return ofAll(toList().distinctBy(comparator));
701     }
702 
703     @Override
704     public <U> Queue<T> distinctBy(Function<? super T, ? extends U> keyExtractor) {
705         Objects.requireNonNull(keyExtractor, "keyExtractor is null");
706         return ofAll(toList().distinctBy(keyExtractor));
707     }
708 
709     @Override
710     public Queue<T> drop(int n) {
711         if (n <= 0) {
712             return this;
713         }
714         if (n >= length()) {
715             return empty();
716         }
717         return new Queue<>(front.drop(n), rear.dropRight(n - front.length()));
718     }
719 
720     @Override
721     public Queue<T> dropUntil(Predicate<? super T> predicate) {
722         return io.vavr.collection.Collections.dropUntil(this, predicate);
723     }
724 
725     @Override
726     public Queue<T> dropWhile(Predicate<? super T> predicate) {
727         Objects.requireNonNull(predicate, "predicate is null");
728         return dropUntil(predicate.negate());
729     }
730 
731     @Override
732     public Queue<T> dropRight(int n) {
733         if (n <= 0) {
734             return this;
735         }
736         if (n >= length()) {
737             return empty();
738         }
739         return new Queue<>(front.dropRight(n - rear.length()), rear.drop(n));
740     }
741 
742     @Override
743     public Queue<T> dropRightUntil(Predicate<? super T> predicate) {
744         return io.vavr.collection.Collections.dropUntil(reverse(), predicate).reverse();
745     }
746 
747     @Override
748     public Queue<T> dropRightWhile(Predicate<? super T> predicate) {
749         Objects.requireNonNull(predicate, "predicate is null");
750         return dropRightUntil(predicate.negate());
751     }
752 
753     @Override
754     public Queue<T> filter(Predicate<? super T> predicate) {
755         Objects.requireNonNull(predicate, "predicate is null");
756         final io.vavr.collection.List<T> filtered = toList().filter(predicate);
757 
758         if (filtered.isEmpty()) {
759             return empty();
760         } else if (filtered.length() == length()) {
761             return this;
762         } else {
763             return ofAll(filtered);
764         }
765     }
766 
767     @Override
768     public <U> Queue<U> flatMap(Function<? super T, ? extends Iterable<? extends U>> mapper) {
769         Objects.requireNonNull(mapper, "mapper is null");
770         if (isEmpty()) {
771             return empty();
772         } else {
773             return new Queue<>(front.flatMap(mapper), rear.flatMap(mapper));
774         }
775     }
776 
777     @Override
778     public T get(int index) {
779         if (isEmpty()) {
780             throw new IndexOutOfBoundsException("get(" + index + ") on empty Queue");
781         }
782         if (index < 0) {
783             throw new IndexOutOfBoundsException("get(" + index + ")");
784         }
785         final int length = front.length();
786         if (index < length) {
787             return front.get(index);
788         } else {
789             final int rearIndex = index - length;
790             final int rearLength = rear.length();
791             if (rearIndex < rearLength) {
792                 final int reverseRearIndex = rearLength - rearIndex - 1;
793                 return rear.get(reverseRearIndex);
794             } else {
795                 throw new IndexOutOfBoundsException("get(" + index + ") on Queue of length " + length());
796             }
797         }
798     }
799 
800     @Override
801     public <C> Map<C, Queue<T>> groupBy(Function<? super T, ? extends C> classifier) {
802         return io.vavr.collection.Collections.groupBy(this, classifier, Queue::ofAll);
803     }
804 
805     @Override
806     public Iterator<Queue<T>> grouped(int size) {
807         return sliding(size, size);
808     }
809 
810     @Override
811     public boolean hasDefiniteSize() {
812         return true;
813     }
814 
815     @Override
816     public T head() {
817         if (isEmpty()) {
818             throw new NoSuchElementException("head of empty " + stringPrefix());
819         } else {
820             return front.head();
821         }
822     }
823 
824     @Override
825     public int indexOf(T element, int from) {
826         final int frontIndex = front.indexOf(element, from);
827         if (frontIndex != -1) {
828             return frontIndex;
829         } else {
830             // we need to reverse because we search the first occurrence
831             final int rearIndex = rear.reverse().indexOf(element, from - front.length());
832             return (rearIndex == -1) ? -1 : rearIndex + front.length();
833         }
834     }
835 
836     @Override
837     public Queue<T> init() {
838         if (isEmpty()) {
839             throw new UnsupportedOperationException("init of empty " + stringPrefix());
840         } else if (rear.isEmpty()) {
841             return new Queue<>(front.init(), rear);
842         } else {
843             return new Queue<>(front, rear.tail());
844         }
845     }
846 
847     @Override
848     public Queue<T> insert(int index, T element) {
849         if (index < 0) {
850             throw new IndexOutOfBoundsException("insert(" + index + ", element)");
851         }
852         final int length = front.length();
853         if (index <= length) {
854             return new Queue<>(front.insert(index, element), rear);
855         } else {
856             final int rearIndex = index - length;
857             final int rearLength = rear.length();
858             if (rearIndex <= rearLength) {
859                 final int reverseRearIndex = rearLength - rearIndex;
860                 return new Queue<>(front, rear.insert(reverseRearIndex, element));
861             } else {
862                 throw new IndexOutOfBoundsException("insert(" + index + ", element) on Queue of length " + length());
863             }
864         }
865     }
866 
867     @SuppressWarnings("unchecked")
868     @Override
869     public Queue<T> insertAll(int index, Iterable<? extends T> elements) {
870         Objects.requireNonNull(elements, "elements is null");
871         if (index < 0) {
872             throw new IndexOutOfBoundsException("insertAll(" + index + ", elements)");
873         }
874         final int length = front.length();
875         if (index <= length) {
876             if (isEmpty() && elements instanceof Queue) {
877                 return (Queue<T>) elements;
878             } else {
879                 final io.vavr.collection.List<T> newFront = front.insertAll(index, elements);
880                 return (newFront == front) ? this : new Queue<>(newFront, rear);
881             }
882         } else {
883             final int rearIndex = index - length;
884             final int rearLength = rear.length();
885             if (rearIndex <= rearLength) {
886                 final int reverseRearIndex = rearLength - rearIndex;
887                 final io.vavr.collection.List<T> newRear = rear.insertAll(reverseRearIndex, io.vavr.collection.List.ofAll(elements).reverse());
888                 return (newRear == rear) ? this : new Queue<>(front, newRear);
889             } else {
890                 throw new IndexOutOfBoundsException("insertAll(" + index + ", elements) on Queue of length " + length());
891             }
892         }
893     }
894 
895     @Override
896     public Queue<T> intersperse(T element) {
897         if (isEmpty()) {
898             return this;
899         } else if (rear.isEmpty()) {
900             return new Queue<>(front.intersperse(element), rear);
901         } else {
902             return new Queue<>(front.intersperse(element), rear.intersperse(element).append(element));
903         }
904     }
905 
906     /**
907      * A {@code Queue} is computed synchronously.
908      *
909      * @return false
910      */
911     @Override
912     public boolean isAsync() {
913         return false;
914     }
915 
916     @Override
917     public boolean isEmpty() {
918         return front.isEmpty();
919     }
920 
921     /**
922      * A {@code Queue} is computed eagerly.
923      *
924      * @return false
925      */
926     @Override
927     public boolean isLazy() {
928         return false;
929     }
930 
931     @Override
932     public boolean isTraversableAgain() {
933         return true;
934     }
935 
936     @Override
937     public int lastIndexOf(T element, int end) {
938         return toList().lastIndexOf(element, end);
939     }
940 
941     @Override
942     public int length() {
943         return front.length() + rear.length();
944     }
945 
946     @Override
947     public <U> Queue<U> map(Function<? super T, ? extends U> mapper) {
948         Objects.requireNonNull(mapper, "mapper is null");
949         return new Queue<>(front.map(mapper), rear.map(mapper));
950     }
951 
952     @Override
953     public Queue<T> orElse(Iterable<? extends T> other) {
954         return isEmpty() ? ofAll(other) : this;
955     }
956 
957     @Override
958     public Queue<T> orElse(Supplier<? extends Iterable<? extends T>> supplier) {
959         return isEmpty() ? ofAll(supplier.get()) : this;
960     }
961 
962     @Override
963     public Queue<T> padTo(int length, T element) {
964         final int actualLength = length();
965         if (length <= actualLength) {
966             return this;
967         } else {
968             return ofAll(toList().padTo(length, element));
969         }
970     }
971 
972     @Override
973     public Queue<T> leftPadTo(int length, T element) {
974         final int actualLength = length();
975         if (length <= actualLength) {
976             return this;
977         } else {
978             return ofAll(toList().leftPadTo(length, element));
979         }
980     }
981 
982     @Override
983     public Queue<T> patch(int from, Iterable<? extends T> that, int replaced) {
984         from = from < 0 ? 0 : from;
985         replaced = replaced < 0 ? 0 : replaced;
986         Queue<T> result = take(from).appendAll(that);
987         from += replaced;
988         result = result.appendAll(drop(from));
989         return result;
990     }
991 
992     @Override
993     public Tuple2<Queue<T>, Queue<T>> partition(Predicate<? super T> predicate) {
994         Objects.requireNonNull(predicate, "predicate is null");
995         return toList().partition(predicate).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue);
996     }
997 
998     @Override
999     public Queue<Queue<T>> permutations() {
1000         return ofAll(toList().permutations().map(io.vavr.collection.List::toQueue));
1001     }
1002 
1003     @Override
1004     public Queue<T> prepend(T element) {
1005         return new Queue<>(front.prepend(element), rear);
1006     }
1007 
1008     @SuppressWarnings("unchecked")
1009     @Override
1010     public Queue<T> prependAll(Iterable<? extends T> elements) {
1011         Objects.requireNonNull(elements, "elements is null");
1012         if (isEmpty() && elements instanceof Queue) {
1013             return (Queue<T>) elements;
1014         } else {
1015             final io.vavr.collection.List<T> newFront = front.prependAll(elements);
1016             return (newFront == front) ? this : new Queue<>(newFront, rear);
1017         }
1018     }
1019 
1020     @Override
1021     public Queue<T> remove(T element) {
1022         final io.vavr.collection.List<T> removed = toList().remove(element);
1023         return ofAll(removed.length() == length() ? this : removed);
1024     }
1025 
1026     @Override
1027     public Queue<T> removeFirst(Predicate<T> predicate) {
1028         final io.vavr.collection.List<T> removed = toList().removeFirst(predicate);
1029         return ofAll(removed.length() == length() ? this : removed);
1030     }
1031 
1032     @Override
1033     public Queue<T> removeLast(Predicate<T> predicate) {
1034         final io.vavr.collection.List<T> removed = toList().removeLast(predicate);
1035         return ofAll(removed.length() == length() ? this : removed);
1036     }
1037 
1038     @Override
1039     public Queue<T> removeAt(int index) {
1040         return ofAll(toList().removeAt(index));
1041     }
1042 
1043     @Override
1044     public Queue<T> removeAll(T element) {
1045         return io.vavr.collection.Collections.removeAll(this, element);
1046     }
1047 
1048     @Override
1049     public Queue<T> replace(T currentElement, T newElement) {
1050         final io.vavr.collection.List<T> newFront = front.replace(currentElement, newElement);
1051         final io.vavr.collection.List<T> newRear = rear.replace(currentElement, newElement);
1052         return newFront.size() + newRear.size() == 0 ? empty()
1053                                                      : newFront == front && newRear == rear ? this
1054                                                                                             : new Queue<>(newFront, newRear);
1055     }
1056 
1057     @Override
1058     public Queue<T> replaceAll(T currentElement, T newElement) {
1059         final io.vavr.collection.List<T> newFront = front.replaceAll(currentElement, newElement);
1060         final io.vavr.collection.List<T> newRear = rear.replaceAll(currentElement, newElement);
1061         return newFront.size() + newRear.size() == 0 ? empty()
1062                                                      : newFront == front && newRear == rear ? this
1063                                                                                             : new Queue<>(newFront, newRear);
1064     }
1065 
1066     @Override
1067     public Queue<T> reverse() {
1068         return isEmpty() ? this : ofAll(toList().reverse());
1069     }
1070 
1071     @Override
1072     public Queue<T> scan(T zero, BiFunction<? super T, ? super T, ? extends T> operation) {
1073         return scanLeft(zero, operation);
1074     }
1075 
1076     @Override
1077     public <U> Queue<U> scanLeft(U zero, BiFunction<? super U, ? super T, ? extends U> operation) {
1078         return io.vavr.collection.Collections.scanLeft(this, zero, operation, Iterator::toQueue);
1079     }
1080 
1081     @Override
1082     public <U> Queue<U> scanRight(U zero, BiFunction<? super T, ? super U, ? extends U> operation) {
1083         return io.vavr.collection.Collections.scanRight(this, zero, operation, Iterator::toQueue);
1084     }
1085 
1086     @Override
1087     public Queue<T> shuffle() {
1088         return io.vavr.collection.Collections.shuffle(this, Queue::ofAll);
1089     }
1090 
1091     @Override
1092     public Queue<T> slice(int beginIndex, int endIndex) {
1093         return ofAll(toList().slice(beginIndex, endIndex));
1094     }
1095 
1096     @Override
1097     public Iterator<Queue<T>> slideBy(Function<? super T, ?> classifier) {
1098         return iterator().slideBy(classifier).map(Queue::ofAll);
1099     }
1100 
1101     @Override
1102     public Iterator<Queue<T>> sliding(int size) {
1103         return sliding(size, 1);
1104     }
1105 
1106     @Override
1107     public Iterator<Queue<T>> sliding(int size, int step) {
1108         return iterator().sliding(size, step).map(Queue::ofAll);
1109     }
1110 
1111     @Override
1112     public Queue<T> sorted() {
1113         return ofAll(toList().sorted());
1114     }
1115 
1116     @Override
1117     public Queue<T> sorted(Comparator<? super T> comparator) {
1118         Objects.requireNonNull(comparator, "comparator is null");
1119         return ofAll(toList().sorted(comparator));
1120     }
1121 
1122     @Override
1123     public <U extends Comparable<? super U>> Queue<T> sortBy(Function<? super T, ? extends U> mapper) {
1124         return sortBy(U::compareTo, mapper);
1125     }
1126 
1127     @Override
1128     public <U> Queue<T> sortBy(Comparator<? super U> comparator, Function<? super T, ? extends U> mapper) {
1129         final Function<? super T, ? extends U> domain = Function1.of(mapper::apply).memoized();
1130         return toJavaStream()
1131                 .sorted((e1, e2) -> comparator.compare(domain.apply(e1), domain.apply(e2)))
1132                 .collect(collector());
1133     }
1134 
1135     @Override
1136     public Tuple2<Queue<T>, Queue<T>> span(Predicate<? super T> predicate) {
1137         Objects.requireNonNull(predicate, "predicate is null");
1138         return toList().span(predicate).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue);
1139     }
1140 
1141     @Override
1142     public Tuple2<Queue<T>, Queue<T>> splitAt(int n) {
1143         return toList().splitAt(n).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue);
1144     }
1145 
1146     @Override
1147     public Tuple2<Queue<T>, Queue<T>> splitAt(Predicate<? super T> predicate) {
1148         return toList().splitAt(predicate).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue);
1149     }
1150 
1151     @Override
1152     public Tuple2<Queue<T>, Queue<T>> splitAtInclusive(Predicate<? super T> predicate) {
1153         return toList().splitAtInclusive(predicate).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue);
1154     }
1155 
1156     @Override
1157     public boolean startsWith(Iterable<? extends T> that, int offset) {
1158         return toList().startsWith(that, offset);
1159     }
1160 
1161     @Override
1162     public Queue<T> subSequence(int beginIndex) {
1163         if (beginIndex < 0 || beginIndex > length()) {
1164             throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ")");
1165         } else {
1166             return drop(beginIndex);
1167         }
1168     }
1169 
1170     @Override
1171     public Queue<T> subSequence(int beginIndex, int endIndex) {
1172         Collections.subSequenceRangeCheck(beginIndex, endIndex, length());
1173         if (beginIndex == endIndex) {
1174             return empty();
1175         } else if (beginIndex == 0 && endIndex == length()) {
1176             return this;
1177         } else {
1178             return ofAll(toList().subSequence(beginIndex, endIndex));
1179         }
1180     }
1181 
1182     @Override
1183     public Queue<T> tail() {
1184         if (isEmpty()) {
1185             throw new UnsupportedOperationException("tail of empty " + stringPrefix());
1186         } else {
1187             return new Queue<>(front.tail(), rear);
1188         }
1189     }
1190 
1191     @Override
1192     public Queue<T> take(int n) {
1193         if (n <= 0) {
1194             return empty();
1195         }
1196         if (n >= length()) {
1197             return this;
1198         }
1199         final int frontLength = front.length();
1200         if (n < frontLength) {
1201             return new Queue<>(front.take(n), io.vavr.collection.List.empty());
1202         } else if (n == frontLength) {
1203             return new Queue<>(front, io.vavr.collection.List.empty());
1204         } else {
1205             return new Queue<>(front, rear.takeRight(n - frontLength));
1206         }
1207     }
1208 
1209     @Override
1210     public Queue<T> takeRight(int n) {
1211         if (n <= 0) {
1212             return empty();
1213         }
1214         if (n >= length()) {
1215             return this;
1216         }
1217         final int rearLength = rear.length();
1218         if (n < rearLength) {
1219             return new Queue<>(rear.take(n).reverse(), io.vavr.collection.List.empty());
1220         } else if (n == rearLength) {
1221             return new Queue<>(rear.reverse(), io.vavr.collection.List.empty());
1222         } else {
1223             return new Queue<>(front.takeRight(n - rearLength), rear);
1224         }
1225     }
1226 
1227     @Override
1228     public Queue<T> takeUntil(Predicate<? super T> predicate) {
1229         Objects.requireNonNull(predicate, "predicate is null");
1230         final io.vavr.collection.List<T> taken = toList().takeUntil(predicate);
1231         return taken.length() == length() ? this : ofAll(taken);
1232     }
1233 
1234     /**
1235      * Transforms this {@code Queue}.
1236      *
1237      * @param f   A transformation
1238      * @param <U> Type of transformation result
1239      * @return An instance of type {@code U}
1240      * @throws NullPointerException if {@code f} is null
1241      */
1242     public <U> U transform(Function<? super Queue<T>, ? extends U> f) {
1243         Objects.requireNonNull(f, "f is null");
1244         return f.apply(this);
1245     }
1246 
1247     @Override
1248     public <T1, T2> Tuple2<Queue<T1>, Queue<T2>> unzip(
1249             Function<? super T, Tuple2<? extends T1, ? extends T2>> unzipper) {
1250         Objects.requireNonNull(unzipper, "unzipper is null");
1251         return toList().unzip(unzipper).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue);
1252     }
1253 
1254     @Override
1255     public <T1, T2, T3> Tuple3<Queue<T1>, Queue<T2>, Queue<T3>> unzip3(Function<? super T, Tuple3<? extends T1, ? extends T2, ? extends T3>> unzipper) {
1256         Objects.requireNonNull(unzipper, "unzipper is null");
1257         return toList().unzip3(unzipper).map(io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue, io.vavr.collection.List::toQueue);
1258     }
1259 
1260     @Override
1261     public Queue<T> update(int index, T element) {
1262         return ofAll(toList().update(index, element));
1263     }
1264 
1265     @Override
1266     public Queue<T> update(int index, Function<? super T, ? extends T> updater) {
1267         Objects.requireNonNull(updater, "updater is null");
1268         return update(index, updater.apply(get(index)));
1269     }
1270 
1271     @Override
1272     public <U> Queue<Tuple2<T, U>> zip(Iterable<? extends U> that) {
1273         return zipWith(that, Tuple::of);
1274     }
1275 
1276     @SuppressWarnings("unchecked")
1277     @Override
1278     public <U, R> Queue<R> zipWith(Iterable<? extends U> that, BiFunction<? super T, ? super U, ? extends R> mapper) {
1279         Objects.requireNonNull(that, "that is null");
1280         Objects.requireNonNull(mapper, "mapper is null");
1281         return ofAll(toList().zipWith(that, mapper));
1282     }
1283 
1284     @Override
1285     public <U> Queue<Tuple2<T, U>> zipAll(Iterable<? extends U> that, T thisElem, U thatElem) {
1286         Objects.requireNonNull(that, "that is null");
1287         return ofAll(toList().zipAll(that, thisElem, thatElem));
1288     }
1289 
1290     @Override
1291     public Queue<Tuple2<T, Integer>> zipWithIndex() {
1292         return zipWithIndex(Tuple::of);
1293     }
1294 
1295     @Override
1296     public <U> Queue<U> zipWithIndex(BiFunction<? super T, ? super Integer, ? extends U> mapper) {
1297         Objects.requireNonNull(mapper, "mapper is null");
1298         return ofAll(toList().zipWithIndex(mapper));
1299     }
1300 
1301     private Object readResolve() {
1302         return isEmpty() ? EMPTY : this;
1303     }
1304 
1305     @Override
1306     public String stringPrefix() {
1307         return "Queue";
1308     }
1309 
1310     @Override
1311     public boolean equals(Object o) {
1312         return io.vavr.collection.Collections.equals(this, o);
1313     }
1314 
1315     @Override
1316     public int hashCode() {
1317         return io.vavr.collection.Collections.hashOrdered(this);
1318     }
1319 }